/**

 @Name：layui.table 表格操作
 @Author：贤心
 @License：MIT
    
 */

layui.define(['laytpl', 'laypage', 'layer', 'util'], function(exports) {
	"use strict";
	
	var $ = layui.$,
		laytpl = layui.laytpl,
		laypage = layui.laypage,
		layer = layui.layer,
		util = layui.util,
		hint = layui.hint(),
		device = layui.device()

		//外部接口
		,table = {
		    //全局配置项
			config: {
				checkName: 'LAY_CHECKED' //是否选中状态的字段名
				,indexName: 'LAY_TABLE_INDEX' //下标索引名
			} 
			//数据缓存
			,cache: []
			,index: layui.table ? (layui.table.index + 10000) : 0 //设置全局项
			,set: function(options) {
				var that = this;
				that.config = $.extend({}, that.config, options);
				return that;
			}
			//事件监听
			,on: function(events, callback) {
				return layui.onevent.call(this, MOD_NAME, events, callback);
			}
		}

		//操作当前实例
		,thisTable = function() {
			var that = this,
				options = that.config,
				id = options.id || options.index;

			if(id) {
				thisTable.that[id] = that; //记录当前实例对象
				thisTable.config[id] = options; //记录当前实例配置项
			}

			return {
				reload: function(options) {
					that.loading();
					that.reload.call(that, options);
				},
				refresh: function(t, page) {
					that.loading(); //wfs
					if(t)
						that.config.where = t;
					if(page)
						that.config.page.curr = 1;
					that.pullData(page || that.page, t);
				},
				getObj: function() { //wfs
					that.cache = table.cache[that.key];
					return that;
				},
				setColsWidth: function(isHide) {
					that.setColsWidth.call(that,isHide);
				},
				resize: function(isHide) { //重置表格尺寸/结构
					that.resize.call(that,isHide);
				},
				config: options
			}
		}

		//获取当前实例配置项
		,getThisTableConfig = function(id) {
			var config = thisTable.config[id];
			if(!config) hint.error('The ID option was not found in the table instance');
			return config || null;
		}

		//字符常量
		,
		MOD_NAME = 'table',
		ELEM = '.layui-table',
		THIS = 'layui-this',
		SHOW = 'layui-show',
		HIDE = 'layui-hide',
		DISABLED = 'layui-disabled',
		NONE = 'layui-none'
		,
		ELEM_VIEW = 'layui-table-view',
		ELEM_TOOL = '.layui-table-tool',
		ELEM_BOX = '.layui-table-box',
		ELEM_INIT = '.layui-table-init',
		ELEM_HEADER = '.layui-table-header',
		ELEM_BODY = '.layui-table-body',
		ELEM_MAIN = '.layui-table-main',
		ELEM_FIXED = '.layui-table-fixed',
		ELEM_FIXL = '.layui-table-fixed-l',
		ELEM_FIXR = '.layui-table-fixed-r',
		ELEM_TOTAL = '.layui-table-total',
		ELEM_PAGE = '.layui-table-page',
		ELEM_SORT = '.layui-table-sort',
		ELEM_EDIT = 'layui-table-edit',
		ELEM_HOVER = 'layui-table-hover'
        ,
        TREE_ID='treeId',
        TREE_UPID='treeUpId',
        TREE_SHOW_NAME='treeName',
        TREE_KEY_MAP='tree_key_map'
        
		//thead区域模板
		,TPL_HEADER = function(options) {
			var rowCols = '{{#if(item2.colspan){}} colspan="{{item2.colspan}}"{{#} if(item2.rowspan){}} rowspan="{{item2.rowspan}}"{{#}}}';

			options = options || {};
			return ['<table  cellspacing="0" cellpadding="0" border="0" class="layui-table" ', '{{# if(d.data.skin){ }}lay-skin="{{d.data.skin}}"{{# } }} {{# if(d.data.size){ }}lay-size="{{d.data.size}}"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>', '<thead>', '{{# layui.each(d.data.cols, function(i1, item1){ }}', '<tr>', '{{# layui.each(item1, function(i2, item2){ }}', '{{# if(item2.fixed && item2.fixed !== "right"){ left = true; } }}', '{{# if(item2.fixed === "right"){ right = true; } }}', function() {
					if(options.fixed && options.fixed !== 'right') {
						return '{{# if(item2.fixed && item2.fixed !== "right"){ }}';
					}
					if(options.fixed === 'right') {
						return '{{# if(item2.fixed === "right"){ }}';
					}
					return '';
				}(), '{{# var isSort = !(item2.colGroup) && item2.sort; }}', '<th data-field="{{ item2.field||i2 }}" data-key="{{d.index}}-{{i1}}-{{i2}}" {{# if( item2.parentKey){ }}data-parentkey="{{ item2.parentKey }}"{{# } }} {{# if(item2.minWidth){ }}data-minwidth="{{item2.minWidth}}"{{# } }} ' + rowCols + ' {{# if(item2.unresize || item2.colGroup){ }}data-unresize="true"{{# } }} class="{{# if(item2.hide){ }}layui-hide{{# } }}{{# if(isSort){ }} layui-unselect{{# } }}{{# if(!item2.field){ }} layui-table-col-special{{# } }}">', '<div class="layui-table-cell laytable-cell-', '{{# if(item2.colGroup){ }}', 'group', '{{# } else { }}', '{{d.index}}-{{i1}}-{{i2}}', '{{# if(item2.type !== "normal"){ }}', ' laytable-cell-{{ item2.type }}', '{{# } }}', '{{# } }}', '" {{#if(item2.align){}}align="{{item2.align}}"{{#}}}>', '{{# if(item2.type === "checkbox"){ }}' //复选框
				, '<input type="checkbox" name="layTableCheckbox" class="layui-all-checkbox" {{# if(item2[d.data.checkName]){ }}checked{{# }; }}>',
				'{{# } else { }}', '<span>{{item2.title||""}}</span>', '{{# if(isSort){ }}', '<span class="layui-table-sort layui-inline"><i class="layui-edge layui-table-sort-asc" title="升序"></i><i class="layui-edge layui-table-sort-desc" title="降序"></i></span>', '{{# } }}', '{{# } }}', '</div>', '</th>', (options.fixed ? '{{# }; }}' : ''), '{{# }); }}', '</tr>', '{{# }); }}', '</thead>', '</table>'
			].join('');
		}

		//tbody区域模板
		,TPL_BODY = ['<table cellspacing="0" cellpadding="0" border="0" class="layui-table" ', '{{# if(d.data.skin){ }}lay-skin="{{d.data.skin}}"{{# } }} {{# if(d.data.size){ }}lay-size="{{d.data.size}}"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>', '<tbody></tbody>', '</table>'].join('')

		//主模板
		,TPL_MAIN = ['<div class="layui-border-box {{d.VIEW_CLASS}}" lay-filter="LAY-table-{{d.index}}" lay-id="{{ d.data.id }}" style="{{# if(d.data.width){ }}width:{{d.data.width}}px;{{# } }} {{# if(d.data.height){ }}height:{{d.data.height}}px;{{# } }}">'

			, '{{# if(d.data.toolbar){ }}', '<div class="layui-table-tool">', '<div class="layui-table-tool-temp"></div>', '<div class="layui-table-tool-self"></div>', '</div>', '{{# } }}'

			, '<div class="layui-table-box">', '{{# if(d.data.loading){ }}', '<div class="layui-table-init" style="background-color: #fff;">', '<i class="layui-icon layui-icon-loading layui-icon"></i>', '</div>', '{{# } }}'

			, '{{# var left, right; }}', '<div class="layui-table-header">', TPL_HEADER(), '</div>', '<div class="layui-table-body layui-table-main">', TPL_BODY, '</div>'

			, '{{# if(left){ }}', '<div class="layui-table-fixed layui-table-fixed-l">', '<div class="layui-table-header">', TPL_HEADER({
				fixed: true
			}), '</div>', '<div class="layui-table-body">', TPL_BODY, '</div>', '</div>', '{{# }; }}'

			, '{{# if(right){ }}', '<div class="layui-table-fixed layui-table-fixed-r">', '<div class="layui-table-header">', TPL_HEADER({
				fixed: 'right'
			}), '<div class="layui-table-mend"></div>', '</div>', '<div class="layui-table-body">', TPL_BODY, '</div>', '</div>', '{{# }; }}', '</div>'

			, '{{# if(d.data.totalRow){ }}', '<div class="layui-table-total">', '<table cellspacing="0" cellpadding="0" border="0" class="layui-table" ', '{{# if(d.data.skin){ }}lay-skin="{{d.data.skin}}"{{# } }} {{# if(d.data.size){ }}lay-size="{{d.data.size}}"{{# } }} {{# if(d.data.even){ }}lay-even{{# } }}>', '<tbody><tr><td><div class="layui-table-cell" style="visibility: hidden;">Total</div></td></tr></tbody>', '</table>', '</div>', '{{# } }}'

			, '{{# if(d.data.page){ }}', '<div class="layui-table-page">', '<div id="layui-table-page{{d.index}}"></div>', '</div>', '{{# } }}'

			, '<style class="xw_style">', '{{# layui.each(d.data.cols, function(i1, item1){', 'layui.each(item1, function(i2, item2){ }}', '.laytable-cell-{{d.index}}-{{i1}}-{{i2}}{ ', '{{# if(item2.width){ }}', 'width: {{item2.width}}px;', '{{# } }}', ' }', '{{# });', '}); }}', '</style>', '</div>'
		].join('')

		,
		_WIN = $(window),
		_DOC = $(document)

		//构造器
		,Class = function(options) {
			var that = this;
			that.index = ++table.index;
			that.config = $.extend({}, that.config, table.config, options);
			that.render();
		};

	//默认配置
	Class.prototype.config = {
		limit: 10 //每页显示的数量
		,loading: true //请求数据时，是否显示loading
		,cellMinWidth: 60 //所有单元格默认最小宽度
		,defaultToolbar: ['filter', 'exports', 'print'] //工具栏右侧图标
		,autoSort: true //是否前端自动排序。如果否，则需自主排序（通常为服务端处理好排序）
		,text: {
			none: '无数据'
		}
	};

	//表格渲染
	Class.prototype.render = function() {
		var that = this,
			options = that.config;

		options.elem = $(options.elem);
		options.where = options.where || {};
		options.id = options.id || options.elem.attr('id') || that.index;

		//请求参数的自定义格式
		options.request = $.extend({
			pageName: 'page',
			limitName: 'limit'
		}, options.request)

		//响应数据的自定义格式
		options.response = $.extend({
			statusName: 'code',
			statusCode: 0,
			msgName: 'msg',
			dataName: 'data',
			countName: 'count'
		}, options.response);

		//如果 page 传入 laypage 对象
		if(typeof options.page === 'object') {
			options.limit = options.page.limit || options.limit;
			options.limits = options.page.limits || options.limits;
			that.page = options.page.curr = options.page.curr || 1;
			delete options.page.elem;
			delete options.page.jump;
		}

		if(!options.elem[0]) return that;

		//高度铺满：full-差距值
		if(options.height && /^full-\d+$/.test(options.height)) {
			that.fullHeightGap = options.height.split('-')[1];
			options.height = _WIN.height() - that.fullHeightGap;
		}

		//初始化一些参数
		that.setInit();

		//开始插入替代元素
		var othis = options.elem,
			hasRender = othis.next('.' + ELEM_VIEW)

			//主容器
			,reElem = that.elem = $(laytpl(TPL_MAIN).render({
				VIEW_CLASS: ELEM_VIEW,
				data: options,
				index: that.index //索引
			}));

		options.index = that.index;

		//生成替代元素
		hasRender[0] && hasRender.remove(); //如果已经渲染，则Rerender
		othis.after(reElem);

		//各级容器
		that.layTool = reElem.find(ELEM_TOOL);
		that.layBox = reElem.find(ELEM_BOX);
		that.layHeader = reElem.find(ELEM_HEADER);
		that.layMain = reElem.find(ELEM_MAIN);
		that.layBody = reElem.find(ELEM_BODY);
		that.layFixed = reElem.find(ELEM_FIXED);
		that.layFixLeft = reElem.find(ELEM_FIXL);
		that.layFixRight = reElem.find(ELEM_FIXR);
		that.layTotal = reElem.find(ELEM_TOTAL);
		that.layPage = reElem.find(ELEM_PAGE);

		//初始化工具栏
		that.renderToolbar();

		//让表格平铺
		that.fullSize();

		//如果多级表头，则填补表头高度
		if(options.cols.length > 1) {
			//补全高度
			var th = that.layFixed.find(ELEM_HEADER).find('th');
			th.height(that.layHeader.height() - parseFloat(th.css('padding-top')) - parseFloat(th.css('padding-bottom')));
		}

		that.renderData({code: 0,data: [],total: 0}, 1); // wfs 
		if(that.config.done) { //wfs
			that.config.done({code: 0,data: [],total: 0}, 1);
		}
		//that.pullData(that.page); //请求数据
		that.events(); //事件
	};

	//根据列类型，定制化参数
	Class.prototype.initOpts = function(item) {
		var that = this,
			options = that.config,
			initWidth = {
				checkbox: 36,
				radio: 36,
				space: 15,
				numbers: 47
			};

		//让 type 参数兼容旧版本
		if(item.checkbox) item.type = "checkbox";
		if(item.space) item.type = "space";
		if(!item.type) item.type = "normal";

		if(item.type !== "normal") {
			item.unresize = true;
			item.width = item.width || initWidth[item.type];
		}
	};

	//初始化一些参数
	Class.prototype.setInit = function(type) {
		var that = this,
			options = that.config;

		options.clientWidth = options.width || function() { //获取容器宽度
			//如果父元素宽度为0（一般为隐藏元素），则继续查找上层元素，直到找到真实宽度为止
			var getWidth = function(parent) {
				var width, isNone;
				parent = parent || options.elem.parent()
				width = parent.width();
				try {
					isNone = parent.css('display') === 'none';
				} catch(e) {}
				if(parent[0] && (!width || isNone)) return getWidth(parent.parent());
				return width;
			};
			return getWidth();
		}();

		if(type === 'width') return options.clientWidth;

		//初始化列参数
		layui.each(options.cols, function(i1, item1) {
			layui.each(item1, function(i2, item2) {

				//如果列参数为空，则移除
				if(!item2) {
					item1.splice(i2, 1);
					return;
				}

				item2.key = i1 + '-' + i2;
				item2.hide = item2.hide || false;

				//设置列的父列索引
				//如果是组合列，则捕获对应的子列
				if(item2.colGroup || item2.colspan > 1) {
					var childIndex = 0;
					layui.each(options.cols[i1 + 1], function(i22, item22) {
						//如果子列已经被标注为{HAS_PARENT}，或者子列累计 colspan 数等于父列定义的 colspan，则跳出当前子列循环
						if(item22.HAS_PARENT || (childIndex > 1 && childIndex == item2.colspan)) return;

						item22.HAS_PARENT = true;
						item22.parentKey = i1 + '-' + i2;

						childIndex = childIndex + parseInt(item22.colspan > 1 ? item22.colspan : 1);
					});
					item2.colGroup = true; //标注是组合列
				}

				//根据列类型，定制化参数
				that.initOpts(item2);
			});
		});

	};

	//初始工具栏
	Class.prototype.renderToolbar = function() {
		var that = this,
			options = that.config

		//添加工具栏左侧模板
		var leftDefaultTemp = [
				'<div class="layui-inline" lay-event="add"><i class="layui-icon layui-icon-add-1"></i></div>', '<div class="layui-inline" lay-event="update"><i class="layui-icon layui-icon-edit"></i></div>', '<div class="layui-inline" lay-event="delete"><i class="layui-icon layui-icon-delete"></i></div>'
			].join(''),
			elemToolTemp = that.layTool.find('.layui-table-tool-temp');

		if(options.toolbar === 'default') {
			elemToolTemp.html(leftDefaultTemp);
		} else if(typeof options.toolbar === 'string') {
			var toolbarHtml = $(options.toolbar).html() || '';
			toolbarHtml && elemToolTemp.html(
				laytpl(toolbarHtml).render(options)
			);
		}

		//添加工具栏右侧面板
		var layout = {
				filter: {
					title: '筛选列',
					layEvent: 'LAYTABLE_COLS',
					icon: 'layui-icon-cols'
				},
				exports: {
					title: '导出',
					layEvent: 'LAYTABLE_EXPORT',
					icon: 'layui-icon-export'
				},
				print: {
					title: '打印',
					layEvent: 'LAYTABLE_PRINT',
					icon: 'layui-icon-print'
				}
			},
			iconElem = [];

		if(typeof options.defaultToolbar === 'object') {
			layui.each(options.defaultToolbar, function(i, item) {
				var thisItem = layout[item];
				if(thisItem) {
					iconElem.push('<div class="layui-inline" title="' + thisItem.title + '" lay-event="' + thisItem.layEvent + '">' +
						'<i class="layui-icon ' + thisItem.icon + '"></i>' +
						'</div>');
				}
			});
		}
		that.layTool.find('.layui-table-tool-self').html(iconElem.join(''));
	}

	//同步表头父列的相关值
	Class.prototype.setParentCol = function(hide, parentKey) {
		var that = this,
			options = that.config,
			parentTh = that.layHeader.find('th[data-key="' + options.index + '-' + parentKey + '"]') //获取父列元素
			,parentColspan = parseInt(parentTh.attr('colspan')) || 0;

		if(parentTh[0]) {
			var arrParentKey = parentKey.split('-'),
				getThisCol = options.cols[arrParentKey[0]][arrParentKey[1]];

			hide ? parentColspan-- : parentColspan++;

			parentTh.attr('colspan', parentColspan);
			parentTh[parentColspan < 1 ? 'addClass' : 'removeClass'](HIDE);

			getThisCol.colspan = parentColspan; //同步 colspan 参数
			getThisCol.hide = parentColspan < 1; //同步 hide 参数

			//递归，继续往上查询是否有父列
			var nextParentKey = parentTh.data('parentkey');
			nextParentKey && that.setParentCol(hide, nextParentKey);
		}
	};

	//多级表头补丁
	Class.prototype.setColsPatch = function() {
		var that = this,
			options = that.config

		//同步表头父列的相关值
		layui.each(options.cols, function(i1, item1) {
			layui.each(item1, function(i2, item2) {
				if(item2.hide) {
					that.setParentCol(item2.hide, item2.parentKey);
				}
			});
		});
	};

	//动态分配列宽
	Class.prototype.setColsWidth = function(isHide) {
		var that = this,
			options = that.config,
			colNums = 0 //列个数
			,autoColNums = 0 //自动列宽的列个数
			,autoWidth = 0 //自动列分配的宽度
			,countWidth = 0 //所有列总宽度和
			,cntrWidth = that.setInit('width');

		//统计列个数
		that.eachCols(function(i, item) {
			item.hide || colNums++;
		});

		//减去边框差和滚动条宽
		cntrWidth = cntrWidth - function() {
			return(options.skin === 'line' || options.skin === 'nob') ? 2 : colNums + 1;
		}() - that.getScrollWidth(that.layMain[0]) - 1;

		//计算自动分配的宽度
		var getAutoWidth = function(back) {
			//遍历所有列
			layui.each(options.cols, function(i1, item1) {
				layui.each(item1, function(i2, item2) {
					var width = 0,
						minWidth = item2.minWidth || options.cellMinWidth; //最小宽度

					if(!item2) {
						item1.splice(i2, 1);
						return;
					}

					if(item2.colGroup || item2.hide) return;

					if(!back) {
						width = item2.width || 0;
						if(/\d+%$/.test(width)) { //列宽为百分比
							width = Math.floor((parseFloat(width) / 100) * cntrWidth);
							width < minWidth && (width = minWidth);
						} else if(!width) { //列宽未填写
							item2.width = width = 0;
							autoColNums++;
						}
					} else if(autoWidth && autoWidth < minWidth) {
						autoColNums--;
						width = minWidth;
					}

					if(item2.hide) width = 0;
					countWidth = countWidth + width;
				});
			});

			//如果未填充满，则将剩余宽度平分
			(cntrWidth > countWidth && autoColNums) && (
				autoWidth = (cntrWidth - countWidth) / autoColNums
			);
		}

		getAutoWidth();
		getAutoWidth(true); //重新检测分配的宽度是否低于最小列宽

		//记录自动列数
		that.autoColNums = autoColNums;

		//设置列宽
		that.eachCols(function(i3, item3) {
			var minWidth = item3.minWidth || options.cellMinWidth;
			if(item3.colGroup || item3.hide) return;

			//给位分配宽的列平均分配宽
			if(item3.width === 0) {
				that.getCssRule(options.index + '-' + item3.key, function(item) {
					item.style.width = Math.floor(autoWidth >= minWidth ? autoWidth : minWidth) + 'px';
				});
			}

			//给设定百分比的列分配列宽
			else if(/\d+%$/.test(item3.width)) {
				that.getCssRule(options.index + '-' + item3.key, function(item) {
					item.style.width = Math.floor((parseFloat(item3.width) / 100) * cntrWidth) + 'px';
				});
			}
		});

		//填补 Math.floor 造成的数差
		var patchNums = that.layMain.width() - that.getScrollWidth(that.layMain[0]) -
			that.layMain.children('table').outerWidth();

		if(that.autoColNums && patchNums >= -colNums && patchNums <= colNums) {
			var getEndTh = function(th) {
					var field;
					th = th || that.layHeader.eq(0).find('thead th:last-child')
					field = th.data('field');
					if(!field && th.prev()[0]) {
						return getEndTh(th.prev())
					}
					return th
				},
				th = getEndTh(),
				key = th.data('key');

			that.getCssRule(key, function(item) {
				var width = item.style.width || th.outerWidth();
				item.style.width = (parseFloat(width) + patchNums) + 'px';

				//二次校验，如果仍然出现横向滚动条（通常是 1px 的误差导致）
				if(that.layMain.height() - that.layMain.prop('clientHeight') > 0) {
					item.style.width = (parseFloat(item.style.width) - 1) + 'px';
				}
			});
		}
		if(isHide!==false) that.loading(!0);
	};

	//重置表格尺寸/结构
	Class.prototype.resize = function(isHide) {
		var that = this;
		that.fullSize(); //让表格铺满
		that.setColsWidth(isHide); //自适应列宽
		that.scrollPatch(); //滚动条补丁
	};

	//表格完整重载
	Class.prototype.reload = function(options) {
		var that = this;
		if(that.config.data && that.config.data.constructor === Array) delete that.config.data;
		that.config = $.extend({}, that.config, options);
		that.render();
	};

	//页码
	Class.prototype.page = 1;
    
    /**
     * 重置当前表格的数据（1、普通列表；2树状表格）
     * 将列表数据转成树形结构和符合table展示的列表
     * @param list          列表数据
     * @param field_Id      树形结构主键字段
     * @param field_upId    树形结构上级字段
     * @returns {Array}     [0]表格列表  [1]树形结构
     */
    Class.prototype.resetData=function(list) {
        var that = this,options = that.config;
        var treeList=[];
        if(list==null || list.length<=0) return list;
        var lists = [];
        //设置默认参数
        for (var i = 0; i < list.length; i++) {
            var n = list[i];
            if(options.isTree){
                if(!n.hasOwnProperty("_is_open")){//如果不存在该属性则默认为true
                    n._is_open = true;
                }
                if(!n.hasOwnProperty("is_show")){//如果不存在该属性则默认为true
                    n.is_show = true;
                }
            }
        }
        if(options.isTree && options[TREE_ID]){//树状
            var field_Id= options[TREE_ID];
            var field_upId=options[TREE_UPID];
            //处理树结构
            var fa = function(upId) {
                var _array = [];
                for (var i = 0; i < list.length; i++) {
                    var n = list[i];
                    if (n[field_upId] === upId ) {
                        n.children = fa(n[field_Id]);
                        _array.push(n);
                    }
                }
                return _array;
            }
            treeList = fa(list[0][field_upId],"");//递归
            //处理表格结构
            var fa2=function (l,level,upids) {
                for (var i = 0; i < l.length; i++) {
                    var n = l[i];
                    n._level=level;//设置当前层级
                    n._upIds=upids;
                    lists.push(n);
                    if (n.children&&n.children.length>0) {
                        fa2(n.children,1+level,upids+n[field_Id]);
                    }
                }
                return;
            }
            fa2(treeList,1,"");
        }
        return lists;
    };
    
	//获得数据
	Class.prototype.pullData = function(curr) {
		var that = this,
			options = that.config,
			request = options.request,
			response = options.response,
			sort = function() {
				if(typeof options.initSort === 'object') {
					that.sort(options.initSort.field, options.initSort.type);
				}
			};

		that.startTime = new Date().getTime(); //渲染开始时间

		if(options.url) { //Ajax请求
			var params = {};
			params[request.pageName] = curr;
			params[request.limitName] = options.limit;

			//参数
			var data = $.extend(params, options.where);
			if(options.contentType && options.contentType.indexOf("application/json") == 0) { //提交 json 格式
				data = JSON.stringify(data);
			}
			
			that.loading(true);
			that._gridAjaxIndex =  $.ajax({
				type: options.method || 'get',
				url: options.url,
				contentType: options.contentType,
				data: data,
				dataType: 'json',
				headers: options.headers || {},
				beforeSend: function (XML) {
				    that.loading();
                    if (that._gridAjaxIndex) {
                        that._gridAjaxIndex.isAborted = true;
                        that._gridAjaxIndex.abort();
                    }
                },
				success: function(res) {
					//转义 script wfs
					res.data = $.scriptEncode(res.data);
					
					if(!res.data || !$.isArray(res.data)  || !res.data.data) { //wfs
						that.layFixed.find(".layui-table tbody").html('');
					}
					//如果有数据解析的回调，则获得其返回的数据
					if(typeof options.parseData === 'function') {
						res = options.parseData(res) || res;
					}
					//检查数据格式是否符合规范
					if(res[response.statusName] != response.statusCode) {
						that.layMain.find('tbody').html("");
						that.layFixRight.find('tbody').html("");
						that.layFixLeft.find('tbody').html("");
						that.layTotal.find('tbody td div').html("");
						that.renderTotal([]);
						that.layMain.find('.' + NONE).remove();
						that.layMain.append('<div class="' + NONE + '">' + (
							res[response.msgName] ||
							('返回的数据不符合规范，正确的成功状态码 (' + response.statusName + ') 应为：' 
							+ response.statusCode)
						) + '</div>');
					} else {
					    if(options.isTree){  res.data = that.resetData( res.data ); }
						that.renderData(res, curr, res[response.countName]), sort();
						options.time = (new Date().getTime() - that.startTime) + ' ms'; //耗时（接口请求+视图渲染）
					}
					that.setColsWidth();
					typeof options.done === 'function' && options.done(res, curr, res[response.countName]);
				},
				error: function(e, m) {
				    if (that._gridAjaxIndex&& that._gridAjaxIndex.isAborted) {
                        return false;
                    }
					that.layMain.find('tbody').html("");
					that.layFixRight.find('tbody').html("");
					that.layFixLeft.find('tbody').html("");
					that.layMain.find('.' + NONE).remove();
					that.layMain.append('<div class="' + NONE + '">数据接口请求异常：' + m + '</div>');
					that.renderTotal([]);
					that.setColsWidth();
				}
			});
			
		} else if(options.data && options.data.constructor === Array) { //已知数据
			var res = {},
				startLimit = curr * options.limit - options.limit

			res[response.dataName] = options.data.concat().splice(startLimit, options.limit);
			res[response.countName] = options.data.length;

			that.renderData(res, curr, options.data.length), sort();
			that.setColsWidth();
			typeof options.done === 'function' && options.done(res, curr, res[response.countName]);
		}
	};

	//遍历表头
	Class.prototype.eachCols = function(callback) {
		var that = this;
		table.eachCols(null, callback, that.config.cols);
		return that;
	};
    
    /**
     * 叶子节点显示转换
     * @param o             数据
     * @param fieldName     树显示列名
     * @returns {string}
     */
    Class.prototype.treeConvertShowName=function (o) {
        var that = this,options = that.config;
        var isTreeNode=(o.children&&o.children.length>0);
        var temhtml='<div style="float: left;height: 28px;line-height: 37px;padding-right:2px;padding-left: '+
            function () {
                return isTreeNode ? '2px' : '18px';
            }()
            +'">'
            +function () {//位移量
                var nbspHtml="<i>"//一次位移
                for(var i=1;i<o._level;i++) {
                    nbspHtml = nbspHtml + "&nbsp;&nbsp;&nbsp;&nbsp;";
                }
                nbspHtml=nbspHtml+"</i>";
                return nbspHtml;
            }()
            +function () {//图标或占位符
                return isTreeNode ? '<i class="layui-icon layui-tree-head">&#xe625;</i> ' : '';
            }()
            +'</div>';
        return temhtml;
    };
    
    /**
     * 节点的展开或折叠
     */
    Class.prototype.treeNodeOpen=function (o,_is_open) {
        var that = this
            ,options = that.config
            ,tr = that.layBody.find('tr[data-index="'+ o[table.config.indexName] +'"]');
        o._is_open=_is_open;
        //处理树结构
        var fa = function(e) {
            if(e.children&&e.children.length>0){
                var temList=e.children;
                for (var i = 0; i < temList.length; i++) {
                    var n = temList[i];
                    if(o._is_open){//打开状态的，关闭
                        if(e._is_open&&e.is_show){//该节点显示
                            var temo=that.layBody.find('tr[data-index="'+ n[table.config.indexName] +'"]');
                            temo.show();
                            n.is_show=true;
                        }
                    }else{
                        var temo=that.layBody.find('tr[data-index="'+ n[table.config.indexName] +'"]');
                        temo.hide();
                        n.is_show=false;
                    }
                    fa(n);
                }
            }
        }
        fa(o);
        //处理图标
        var dbClickI=tr.find('.layui-tree-head');
        if(o._is_open){//打开状态
            dbClickI.html('&#xe625;');
        }else{
            dbClickI.html('&#xe623;');
        }
    };
    
	//数据渲染
	Class.prototype.renderData = function(res, curr, count, sort) {
		var that = this,
			options = that.config,
			data = res[options.response.dataName] || [],
			trs = [],
			trs_fixed = [],
			trs_fixed_r = [];

			//渲染视图
		var render = function() { //后续性能提升的重点
			var thisCheckedRowIndex;
			if(!sort && that.sortKey && options.autoSort) {
				return that.sort(that.sortKey.field, that.sortKey.sort, true);
			}
			layui.each(data, function(i1, item1) {
				var tds = [],tds_fixed = [],tds_fixed_r = [],
				numbers = i1 + options.limit * (curr - 1) + 1; //序号

				if(item1.length === 0) return;
				if(!sort) {
					item1[table.config.indexName] = i1;
				}
				
				that.eachCols(function(i3, item3) {
					var field = item3.field || i3,
						key = options.index + '-' + item3.key,
						content = item1[field];

					if(content === undefined || content === null) content = '';
					if(item3.colGroup) return;
                    
                    //wfs
                    var treeImgHtml='';
                    if(options.isTree && options[TREE_SHOW_NAME]== field){
                        treeImgHtml=that.treeConvertShowName(item1);
                    }
                    
					//td内容
					var td = ['<td data-field="' + field + '" data-key="' + key + '" ' + function() { //追加各种属性
						var attr = [];
						if(item3.edit) attr.push('data-edit="' + item3.edit + '"'); //是否允许单元格编辑
						if(item3.align) attr.push('align="' + item3.align + '"'); //对齐方式
						if(item3.templet) attr.push('data-content="' + content + '"'); //自定义模板
						if(item3.toolbar) attr.push('data-off="true"'); //行工具列关闭单元格事件
						if(item3.event) attr.push('lay-event="' + item3.event + '"'); //自定义事件
						if(item3.style) attr.push('style="' + item3.style + '"'); //自定义样式
						if(item3.minWidth) attr.push('data-minwidth="' + item3.minWidth + '"'); //单元格最小宽度
						return attr.join(' ');
					}() + ' class="' + function() { //追加样式
						var classNames = [];
						if(item3.hide) classNames.push(HIDE); //插入隐藏列样式
						if(!item3.field) classNames.push('layui-table-col-special'); //插入特殊列样式
						return classNames.join(' ');
					}() + '">', '<div class="layui-table-cell laytable-cell-' + function() { //返回对应的CSS类标识
						return item3.type === 'normal' ? key :
							(key + ' laytable-cell-' + item3.type);
					}() + '">' +treeImgHtml+ function() {
						var tplData = $.extend(true, { LAY_INDEX: numbers }, item1),
							checkName = table.config.checkName;
						
						//初始化小数位 wfs
						if(content != undefined && item3.dataType == "number") {
							var  gridConfig = (window.__webConfig__ && __webConfig__.xw_grid) || {};
        					var  defaultAcc = gridConfig.numberAcc  || 2;
							var  acc = item3.acc === 0 ? 0 : (item3.acc || defaultAcc);
							var  enabledPermil = gridConfig.enabledPermil === false ? false : true;
							content = Number(content).toFixed(acc);
							if(String(item3.enabledPermil) !="false" && enabledPermil){
								content = $.commafy(content);
							}
						}
						
						if(content != undefined && item3.dataType == "datetime") {
							content =$.getDate(item3.format || 'yyyy-MM-dd HH:mm' ,content);
						}
						
						//渲染不同风格的列
						switch(item3.type) {
							case 'checkbox':
								return '<input type="checkbox" name="layTableCheckbox" ' +
								function() {
									//如果是全选
									if(item3[checkName]) {
										item1[checkName] = item3[checkName];
										return item3[checkName] ? 'checked' : '';
									}
									return tplData[checkName] ? 'checked' : '';
								}() + '>';
								break;
							case 'radio':
								if(tplData[checkName]) {
									thisCheckedRowIndex = i1;
								}
								return '<input type="radio" name="layTableRadio_' + options.index + '" ' +
									(tplData[checkName] ? 'checked' : '') + ' lay-type="layTableRadio">';
								break;
							case 'numbers':
								return numbers;
								break;
						};

						//解析工具列模板
						if(item3.toolbar) {
							return laytpl($(item3.toolbar).html() || '').render(tplData);
						}

						return item3.templet ? function() {
							var dataConfig = {//wfs
								fieid:item3.field,
								value:tplData[item3.field],
								data:tplData,
								item:item3
							}
							return typeof item3.templet === 'function' ?
								item3.templet(dataConfig) :
								laytpl($(item3.templet).html() || String(content)).render(dataConfig)
						}() : content;
						
					}(), '</div></td>'].join('');
                    
					tds.push(td);
					if(item3.fixed && item3.fixed !== 'right') tds_fixed.push(td);
					if(item3.fixed === 'right') tds_fixed_r.push(td);
				});
				
				//tds = that.renderTr(item1,numbers);

				trs.push('<tr data-index="' + i1 + '">' + tds.join('') + '</tr>');
				trs_fixed.push('<tr data-index="' + i1 + '">' + tds_fixed.join('') + '</tr>');
				trs_fixed_r.push('<tr data-index="' + i1 + '">' + tds_fixed_r.join('') + '</tr>');
			});

			that.layBody.scrollTop(0);
			that.layMain.find('.' + NONE).remove();
			that.layMain.find('tbody').html(trs.join(''));
			that.layFixLeft.find('tbody').html(trs_fixed.join(''));
			that.layFixRight.find('tbody').html(trs_fixed_r.join(''));

			typeof thisCheckedRowIndex === 'number' && that.setThisRowChecked(thisCheckedRowIndex);
			that.syncCheckAll();

			//滚动条补丁
			that.haveInit ? that.scrollPatch() : setTimeout(function() {
				that.scrollPatch();
			}, 50);
			that.haveInit = true;

			layer.close(that.tipsIndex);

			//同步表头父列的相关值
			options.HAS_SET_COLS_PATCH || that.setColsPatch();
			options.HAS_SET_COLS_PATCH = true;
		};

		that.key = options.id || options.index;
		table.cache[that.key] = data; //记录数据

		//排序
		if(sort) {
			return render();
		}

		if(data.length === 0) {
			that.layFixed.find(".layui-table tbody").html('');
			that.layMain.find('tbody').html('');
			that.layMain.find('.' + NONE).remove();
			that.layMain.append('<div class="' + NONE + '">' + options.text.none + '</div>');
			//wfs 空数据也显示汇总行和分页
			return that.renderTotal(data), void(options.page && (options.page = $.extend({
				elem: "layui-table-page" + options.index,
				count: count,
				limit: options.limit,
				limits: options.limits || [10, 20, 30, 40, 50, 60, 70, 80, 90],
				groups: 3,
				layout: ["prev", "page", "next", "skip", "count", "limit"],
				prev: '<i class="layui-icon">&#xe603;</i>',
				next: '<i class="layui-icon">&#xe602;</i>',
				jump: function(e, t) {
					t || (that.page = e.curr, options.limit = e.limit, that.loading(), that.pullData(e.curr))
				}
			}, options.page), options.page.count = 1, laypage.render(options.page)));
		}
		
		render(); //渲染数据
		that.renderTotal(data); //数据合计
		that.renderPage(count);//分页渲染
		
		//设置默认层级
		if(options.isTree){
            $.each(data, function(index,o) {
                if(o._level > (options.treeOpenLevel || 1)){
                    that.treeNodeOpen(o,false); 
                }
            });
        }
	};
	
	/**
     * 渲染分页
     */
    Class.prototype.renderPage=function (count) {
        var that = this ,options = that.config;
        //同步分页状态
        if(options.page){
            options.page = $.extend({
                elem: 'layui-table-page' + options.index
                ,count: count
                ,limit: options.limit
                ,limits: options.limits || [10,15,20,30,40,50,60,70,80,90]
                ,groups: 3
                ,layout: ['prev', 'page', 'next', 'skip', 'count', 'limit']
                ,prev: '<i class="layui-icon">&#xe603;</i>'
                ,next: '<i class="layui-icon">&#xe602;</i>'
                ,jump: function(obj, first){
                    if(!first){
                        that.page = obj.curr; //更新页码
                        options.limit = obj.limit; //更新每页条数
                        that.loading();
                        that.pullData(obj.curr);
                    }
                }
            }, options.page);
            options.page.count = count; //更新总条数
            laypage.render(options.page);
        }
    };

	//数据合计行
	Class.prototype.renderTotal = function(data) {
		var that = this,
			options = that.config,
			totalNums = {};

		if(!options.totalRow) return;

		layui.each(data, function(i1, item1) {
			if(item1.length === 0) return;

			that.eachCols(function(i3, item3) {
				var field = item3.field || i3,
					content = item1[field];

				if(item3.totalRow) {
					totalNums[field] = (totalNums[field] || 0) + (parseFloat(content) || 0);
				}
			});
		});

		var tds = [];
		that.eachCols(function(i3, item3) {
			var field = item3.field || i3;

			//td内容
			var td = ['<td data-field="' + field + '" data-key="' + options.index + '-' + item3.key + '" ' + function() {
				var attr = [];
				if(item3.align) attr.push('align="' + item3.align + '"'); //对齐方式
				if(item3.style) attr.push('style="' + item3.style + '"'); //自定义样式
				if(item3.minWidth) attr.push('data-minwidth="' + item3.minWidth + '"'); //单元格最小宽度
				return attr.join(' ');
			}() + ' class="' + function() { //追加样式
				var classNames = [];
				if(item3.hide) classNames.push(HIDE); //插入隐藏列样式
				if(!item3.field) classNames.push('layui-table-col-special'); //插入特殊列样式
				return classNames.join(' ');
			}() + '">', '<div class="layui-table-cell laytable-cell-' + function() { //返回对应的CSS类标识
				var str = (options.index + '-' + item3.key);
				return item3.type === 'normal' ? str :
					(str + ' laytable-cell-' + item3.type);
			}() + '">' + function() {
				
				var text = item3.totalRowText || '';
				
				//wfs
				if(totalNums[field] != undefined && item3.dataType == "number") {
					var  gridConfig = (window.__webConfig__ && __webConfig__.xw_grid) || {};
					var  defaultAcc = gridConfig.numberAcc  || 2;
					var  acc = item3.acc === 0 ? 0 : (item3.acc || defaultAcc);
					var  enabledPermil = gridConfig.enabledPermil === false ? false : true;
					totalNums[field] = Number(totalNums[field]).toFixed(acc);
					if(String(item3.enabledPermil) !="false" && enabledPermil){
						totalNums[field] = $.commafy(totalNums[field]);
					}
				}
				
				return item3.totalRow ? (totalNums[field]  || text) : text; //wfs
			}(), '</div></td>'].join('');

			tds.push(td);
		});

		that.layTotal.find('tbody').html('<tr>' + tds.join('') + '</tr>');
	};

	//找到对应的列元素
	Class.prototype.getColElem = function(parent, key) {
		var that = this,
			options = that.config;
		return parent.eq(0).find('.laytable-cell-' + (options.index + '-' + key) + ':eq(0)');
	};

	//标记当前行选中状态
	Class.prototype.setThisRowChecked = function(index, iscKe) {
		var that = this,
			options = that.config,
			ELEM_CLICK = 'layui-table-click',
			tr = that.layBody.find('tr[data-index="' + index + '"]');
		if(iscKe) {
			tr.addClass(ELEM_CLICK);
		} else {
			tr.addClass(ELEM_CLICK).siblings('tr').removeClass(ELEM_CLICK);
		}
	};

	//数据排序
	Class.prototype.sort = function(th, type, pull, formEvent) {
		var that = this,
			field, res = {},
			options = that.config,
			filter = options.elem.attr('lay-filter'),
			data = table.cache[that.key],
			thisData;

		//字段匹配
		if(typeof th === 'string') {
			that.layHeader.find('th').each(function(i, item) {
				var othis = $(this),
					_field = othis.data('field');
				if(_field === th) {
					th = othis;
					field = _field;
					return false;
				}
			});
		}

		try {
			var field = field || th.data('field'),
				key = th.data('key');

			//如果欲执行的排序已在状态中，则不执行渲染
			if(that.sortKey && !pull) {
				if(field === that.sortKey.field && type === that.sortKey.sort) {
					return;
				}
			}

			var elemSort = that.layHeader.find('th .laytable-cell-' + key).find(ELEM_SORT);
			that.layHeader.find('th').find(ELEM_SORT).removeAttr('lay-sort'); //清除其它标题排序状态
			elemSort.attr('lay-sort', type || null);
			that.layFixed.find('th')
		} catch(e) {
			return hint.error('Table modules: Did not match to field');
		}

		//记录排序索引和类型
		that.sortKey = {
			field: field,
			sort: type
		};

		//默认为前端自动排序。如果否，则需自主排序（通常为服务端处理好排序）
		if(options.autoSort) {
			if(type === 'asc') { //升序
				thisData = layui.sort(data, field);
			} else if(type === 'desc') { //降序
				thisData = layui.sort(data, field, true);
			} else { //清除排序
				thisData = layui.sort(data, table.config.indexName);
				delete that.sortKey;
			}
			
			//wfs
			res[options.response.dataName] = thisData || data;
			that.renderData(res, that.page, that.count, true);
		}

		if(formEvent) {
			layui.event.call(th, MOD_NAME, 'sort(' + filter + ')', {
				field: field,
				type: type
			});
		}
	};

	//请求loading
	Class.prototype.loading = function(hide) {
		var that = this,
			options = that.config;
		if(options.loading) {
			if(hide) {
				that.layInit && that.layInit.remove();
				delete that.layInit;
				that.layBox.find(ELEM_INIT).remove()
			} else {
				that.layInit = $(['<div class="layui-table-init">', '<i class="layui-icon layui-icon-loading layui-icon"></i>', '</div>'].join(''));
				that.layBox.append(that.layInit);
			}
		}
	};

	//同步选中值状态
	Class.prototype.setCheckData = function(index, checked) {
		var that = this,
			options = that.config,
			thisData = table.cache[that.key];
		if(!thisData[index]) return;
		if(thisData[index].constructor === Array) return;
		thisData[index][options.checkName] = checked;
	};
	
	//同步全选按钮状态
	Class.prototype.syncCheckAll = function() {
		var that = this,
			options = that.config,
			checkAllElem = that.layHeader.find('input[name="layTableCheckbox"]'),
			syncColsCheck = function(checked) {
				that.eachCols(function(i, item) {
					if(item.type === 'checkbox') {
						item[options.checkName] = checked;
					}
				});
				return checked;
			};

		if(!checkAllElem[0]) return;

		if(table.checkStatus(that.key).isAll) {
			if(!checkAllElem[0].checked) {
				checkAllElem.prop('checked', true);
			}
			syncColsCheck(true);
		} else {
			if(checkAllElem[0].checked) {
				checkAllElem.prop('checked', false);
			}
			syncColsCheck(false);
		}
	};

	//获取cssRule
	Class.prototype.getCssRule = function(key, callback) {
		var that = this,
			style = that.elem.find('style')[0],
			sheet = style.sheet || style.styleSheet || {},
			rules = sheet.cssRules || sheet.rules;
		layui.each(rules, function(i, item) {
			if(item.selectorText === ('.laytable-cell-' + key)) {
				return callback(item), true;
			}
		});
	};

	//让表格铺满
	Class.prototype.fullSize = function() {
		var that = this,
			options = that.config,
			height = options.height,
			bodyHeight;

		if(that.fullHeightGap) {
			height = _WIN.height() - that.fullHeightGap;
			if(height < 135) height = 135;
			that.elem.css('height', height);
		}

		if(!height) return;

		//减去列头区域的高度
		bodyHeight = parseFloat(height) - (that.layHeader.outerHeight() || 38); //此处的数字常量是为了防止容器处在隐藏区域无法获得高度的问题，暂时只对默认尺寸的表格做支持。

		//减去工具栏的高度
		if(options.toolbar) {
			bodyHeight = bodyHeight - (that.layTool.outerHeight() || 50);
		}

		//减去统计朗的高度
		if(options.totalRow) {
			bodyHeight = bodyHeight - (that.layTotal.outerHeight() || 40);
		}

		//减去分页栏的高度
		if(options.page) {
			bodyHeight = bodyHeight - (that.layPage.outerHeight() || 41) - 2;
		}

		that.layMain.css('height', bodyHeight);
	};

	//获取滚动条宽度
	Class.prototype.getScrollWidth = function(elem) {
		var width = 0;
		if(elem) {
			width = elem.offsetWidth - elem.clientWidth;
		} else {
			elem = document.createElement('div');
			elem.style.width = '100px';
			elem.style.height = '100px';
			elem.style.overflowY = 'scroll';

			document.body.appendChild(elem);
			width = elem.offsetWidth - elem.clientWidth;
			document.body.removeChild(elem);
		}
		return width;
	};

	//滚动条补丁
	Class.prototype.scrollPatch = function() {
		var that = this,
			layMainTable = that.layMain.children('table'),
			scollWidth = that.layMain.width() - that.layMain.prop('clientWidth') //纵向滚动条宽度
			,scollHeight = that.layMain.height() - that.layMain.prop('clientHeight') //横向滚动条高度
			,getScrollWidth = that.getScrollWidth(that.layMain[0]) //获取主容器滚动条宽度，如果有的话
			,outWidth = layMainTable.outerWidth() - that.layMain.width() //表格内容器的超出宽度

			//添加补丁
			,addPatch = function(elem) {
				if(scollWidth && scollHeight) {
					elem = elem.eq(0);
					if(!elem.find('.layui-table-patch')[0]) {
						var patchElem = $('<th class="layui-table-patch"><div class="layui-table-cell"></div></th>'); //补丁元素
						patchElem.find('div').css({
							width: scollWidth
						});
						elem.find('tr').append(patchElem);
					}
				} else {
					elem.find('.layui-table-patch').remove();
				}
			}

		addPatch(that.layHeader);
		addPatch(that.layTotal);

		//固定列区域高度
		var mainHeight = that.layMain.height(),
			fixHeight = mainHeight - scollHeight;
		that.layFixed.find(ELEM_BODY).css('height', layMainTable.height() >= fixHeight ? fixHeight : 'auto');

		//表格宽度小于容器宽度时，隐藏固定列
		that.layFixRight[outWidth > 0 ? 'removeClass' : 'addClass'](HIDE);

		//操作栏
		that.layFixRight.css('right', scollWidth - 1);
	};

	//设置选中 wfs	
	Class.prototype.setSelected = function(index, iscKe, iscKe2) {
		var $tr = this.layBody.find('tr[data-index="' + index + '"]');
		if(this.config.multiSelect == false || this.config.multiSelect == "false") {
			if(iscKe2!==false){
				$tr.find('input[lay-type="layTableRadio"]').prop("checked", true);
			}
		} else {
			$tr.find('input[name="layTableCheckbox"]').prop("checked", true);
		}
		this.setThisRowChecked(index, iscKe);
		this.setCheckData(index, true);
		this.syncCheckAll();
	}

	// wfs 取消选中
	Class.prototype.cancelSelected = function(index) {
		var $tr = this.layBody.find('tr[data-index="' + index + '"]');
		if(this.config.multiSelect == false || this.config.multiSelect == "false") {
			$tr.find('input[lay-type="layTableRadio"]').prop("checked", false);
		} else {
			$tr.find('input[name="layTableCheckbox"]').prop("checked", true);
		}
		that.layBody.find('tr[data-index="' + l + '"]').removeClass("layui-table-click");
		that.setCheckData(l, false);
		that.syncCheckAll();
	}

	//事件处理
	Class.prototype.events = function() {
		var that = this,
			options = that.config,
			_BODY = $('body'),
			dict = {},
			th = that.layHeader.find('th'),
			resizing, ELEM_CELL = '.layui-table-cell',
			filter = options.elem.attr('lay-filter');

		//拖拽调整宽度    
		th.on('mousemove', function(e) {
			var othis = $(this),
				oLeft = othis.offset().left,
				pLeft = e.clientX - oLeft;
			if(othis.data('unresize') || dict.resizeStart) {
				return;
			}
			dict.allowResize = othis.width() - pLeft <= 10; //是否处于拖拽允许区域
			if(dict.allowResize){
				_BODY.addClass('cursor_col-resize');
			}else{
				_BODY.removeClass('cursor_col-resize');
			}
		}).on('mouseleave', function() {
			var othis = $(this);
			if(dict.resizeStart) return;
			_BODY.removeClass('cursor_col-resize');
		}).on('mousedown', function(e) {
			var othis = $(this);
			if(dict.allowResize) {
				var key = othis.data('key');
				e.preventDefault();
				dict.resizeStart = true; //开始拖拽
				dict.offset = [e.clientX, e.clientY]; //记录初始坐标

				that.getCssRule(key, function(item) {
					var width = item.style.width || othis.outerWidth();
					dict.rule = item;
					dict.ruleWidth = parseFloat(width);
					dict.minWidth = othis.data('minwidth') || options.cellMinWidth;
				});
			}
		});

		//拖拽中
		_DOC.on('mousemove', function(e) {
			if(dict.resizeStart) {
				e.preventDefault();
				if(dict.rule) {
					var setWidth = dict.ruleWidth + e.clientX - dict.offset[0];
					if(setWidth < dict.minWidth) setWidth = dict.minWidth;
					dict.rule.style.width = setWidth + 'px';
					layer.close(that.tipsIndex);
				}
				resizing = 1
			}
		}).on('mouseup', function(e) {
			if(dict.resizeStart) {
				dict = {};
				_BODY.removeClass('cursor_col-resize');
				that.scrollPatch();
			}
			if(resizing === 2) {
				resizing = null;
			}
		});

		//排序
		th.on('click', function(e) {
			var othis = $(this),
				elemSort = othis.find(ELEM_SORT),
				nowType = elemSort.attr('lay-sort'),
				type;
			if(!elemSort[0] || resizing === 1) return resizing = 2;
			if(nowType === 'asc') {  type = 'desc'; } else { type = 'asc'; }
			that.sort(othis, type, null, true);
		}).find(ELEM_SORT + ' .layui-edge ').on('click', function(e) {
			var othis = $(this),
				index = othis.index(),
				field = othis.parents('th').eq(0).data('field')
			layui.stope(e);
			if(index === 0) {
				that.sort(field, 'asc', null, true);
			} else {
				that.sort(field, 'desc', null, true);
			}
		});

		//数据行中的事件监听返回的公共对象成员
		var commonMember = function(sets) {
			var othis = $(this),
				index = othis.parents('tr').eq(0).data('index'),
				tr = that.layBody.find('tr[data-index="' + index + '"]'),
				data = table.cache[that.key][index];

			return $.extend({
				tr: tr //行元素
				,data: table.clearCacheKey(data) //当前行数据
				,del: function() { //删除行数据
					table.cache[that.key][index] = [];
					tr.remove();
					that.scrollPatch();
				},
				update: function(fields) { //修改行数据
					fields = fields || {};
					layui.each(fields, function(key, value) {
						if(key in data) {
							var templet, td = tr.children('td[data-field="' + key + '"]');
							data[key] = value;
							that.eachCols(function(i, item2) {
								if(item2.field == key && item2.templet) {
									templet = item2.templet;
								}
							});
							td.children(ELEM_CELL).html(function() {
								return templet ? function() {
									return typeof templet === 'function' ?
										templet(data) :
										laytpl($(templet).html() || value).render(data)
								}() : value;
							}());
							td.data('content', value);
						}
					});
				}
			}, sets);
		};

		//复选框选择
		that.elem.on('click', 'input[name="layTableCheckbox"]', function() { //替代元素的 click 事件
			var checkbox = $(this), isAll=false,
				childs = that.layBody.find('input[name="layTableCheckbox"]'),
				index = checkbox.parents('tr').eq(0).data('index'),
				checked = checkbox[0].checked;

			//全选  wfs
			if($(this).is('.layui-all-checkbox')) {
			    isAll = true;
				childs.each(function(i, item) {
					item.checked = checked;
					that.setCheckData(i, checked);
					if(checked) {
						$(item).parents('tr').addClass("layui-table-click");
					}else{
						$(item).parents('tr').removeClass("layui-table-click");
					}
				});
				that.syncCheckAll();
			} else {
				that.setCheckData(index, checked);
				that.syncCheckAll();
				if(checked) {
					that.layBody.find('tr[data-index="' + index + '"]').addClass("layui-table-click");
				} else {
					that.layBody.find('tr[data-index="' + index + '"]').removeClass("layui-table-click");
				}
				if(options.mergeCheck!='false' && options.mergeCheck ){
					that.selectedMergeCheckbox( checkbox.parents('tr').eq(0) );
				}
			}
			layui.event.call(checkbox[0], MOD_NAME, 'checkbox(' + filter + ')', commonMember.call(checkbox[0], {
				checked: checked,
				type: isAll ? 'all' : 'one'
			}));
		});

		//单选框选择
		that.elem.on('click', 'input[lay-type="layTableRadio"]', function() {
			var radio = $(this),
				checked = radio[0].checked,
				thisData = table.cache[that.key],
				index = radio.parents('tr').eq(0).data('index');

			//重置数据单	选属性
			layui.each(thisData, function(i, item) {
				if(index === i) {
					item.LAY_CHECKED = true;
				} else {
					delete item.LAY_CHECKED;
				}
			});
			that.setThisRowChecked(index);
			layui.event.call(this, MOD_NAME, 'radio(' + filter + ')', commonMember.call(this, {
				checked: checked
			}));
		});

		//行事件
		that.layBody.on('mouseenter', 'tr', function() { //鼠标移入行
			var othis = $(this), index = othis.index();
			that.layBody.find('tr:eq(' + index + ')').addClass(ELEM_HOVER)
		}).on('mouseleave', 'tr', function() { //鼠标移出行
			var othis = $(this), index = othis.index();
			that.layBody.find('tr:eq(' + index + ')').removeClass(ELEM_HOVER)
		}).on('click', 'tr', function(e) { //单击行
			//wfs
			var isMultiSelect = that.config.multiSelect, l = $(this).data("index");
			if(!$(e.target).is('.layui-icon') &&
				!$(e.target).is('input[name="layTableCheckbox"]') &&
				!$(e.target).is('.laytable-cell-checkbox') &&
				!(e.shiftKey || e.ctrlKey)
			) {
				if(isMultiSelect == false || isMultiSelect == "false") {
					that.layBody.find('input[lay-type="layTableRadio"]').each(function(e, t) {
						that.setCheckData(e, false);
					});
				} else {
					that.layBody.find('input[name="layTableCheckbox"]').each(function(e, t) {
						t.checked = false;
						that.setCheckData(e, false);
					});
				}
				that.setSelected(l);
			} else if(e.shiftKey || e.ctrlKey && isMultiSelect=='true') {
				if(that.layBody.find('tr[data-index="' + l + '"]').hasClass('layui-table-click')) {
					that.cancelSelected(l);
				} else {
					that.setSelected(l, true);
				}
			}
			if(options.mergeCheck != 'false' && options.mergeCheck){
				if( !$(e.target).is('input[name="layTableCheckbox"]') ){
					that.selectedMergeCheckbox( $(this) );
				}
			}
			setRowEvent.call(this, 'row');
		}).on('dblclick', 'tr', function() { //双击行
			setRowEvent.call(this, 'rowDouble');
		});

		//创建行单击、双击事件监听
		var setRowEvent = function(eventType) {
			var othis = $(this);
			layui.event.call(this,
				MOD_NAME, eventType + '(' + filter + ')', commonMember.call(othis.children('td')[0])
			);
		};

		//单元格移入事件
		that.layBody.on('mouseenter', 'td', function() {
			var elemCell = $(this).children(ELEM_CELL);
			if(elemCell.prop('scrollWidth') > elemCell.outerWidth()){
				if(elemCell.find('.layui-table-grid-down')[0]) return;
				$(this).attr("title", $(this).text()) //wfs
			}
		});

		//同步滚动条
		that.layMain.on('scroll', function() {
			var othis = $(this),
				scrollLeft = othis.scrollLeft(),
				scrollTop = othis.scrollTop();

			that.layHeader.scrollLeft(scrollLeft);
			that.layTotal.scrollLeft(scrollLeft);
			that.layFixed.find(ELEM_BODY).scrollTop(scrollTop);

			layer.close(that.tipsIndex);
		});

		//自适应
		_WIN.on('resize', function() {
			that.resize();
		});
		
		
		 /**
         * wfs - 树形节点点击事件（隐藏展开下级节点）
         */
        that.elem.on('click', 'i.layui-tree-head', function(){
            var o= table.cache[that.key][$(this).parents('tr').eq(0).data('index')];
            that.treeNodeOpen(o,!o._is_open);
        });
		
	};
	
	//自动选中合并复选框 - wfs
    Class.prototype.selectedMergeCheckbox = function(tr,checked){
    	var $th = this;
    	var isMultiSelect = (this.config.multiSelect == false || this.config.multiSelect == "false")
		var $td_check = tr.find('[data-field="_check"]');
        var $td_rowspan  = $td_check.attr("rowspan");
        if( $td_check.length>0 && $td_check.css("display") !='none' && $td_rowspan > 1 ){
        	var index = tr.data('index');
    		for (var i=0;i<$td_rowspan; i++ ) {
    			if( checked || tr.is(".layui-table-click") ){
    				$th.setSelected(index ++,true,!isMultiSelect ? true : ( i ==0 ? true: false ));
    			}else{
    				$th.cancelSelected(index ++);
    			}
    		}
    	}else if(tr && $td_check.length < 1 || $td_check.css("display") == 'none' ){
    		$th.selectedMergeCheckbox( tr.prev() , checked || tr.is(".layui-table-click") );
    	}
    };
	
	//初始化
	table.init = function(filter, settings) {
		settings = settings || {};
		var that = this,
			elemTable = filter ? $('table[lay-filter="' + filter + '"]') : $(ELEM + '[lay-data]'),
			errorTips = 'Table element property lay-data configuration item has a syntax error: ';

		//遍历数据表格
		elemTable.each(function() {
			var othis = $(this),
				tableData = othis.attr('lay-data');

			try {
				tableData = new Function('return ' + tableData)();
			} catch(e) {
				hint.error(errorTips + tableData)
			}

			var cols = [],
				options = $.extend({
					elem: this,
					cols: [],
					data: [],
					skin: othis.attr('lay-skin') //风格
						,
					size: othis.attr('lay-size') //尺寸
						,
					even: typeof othis.attr('lay-even') === 'string' //偶数行背景
				}, table.config, settings, tableData);

			filter && othis.hide();

			//获取表头数据
			othis.find('thead>tr').each(function(i) {
				options.cols[i] = [];
				$(this).children().each(function(ii) {
					var th = $(this),
						itemData = th.attr('lay-data');

					try {
						itemData = new Function('return ' + itemData)();
					} catch(e) {
						return hint.error(errorTips + itemData)
					}

					var row = $.extend({
						title: th.text(),
						colspan: th.attr('colspan') || 0 //列单元格
							,
						rowspan: th.attr('rowspan') || 0 //行单元格
					}, itemData);

					if(row.colspan < 2) cols.push(row);
					options.cols[i].push(row);
				});
			});

			//获取表体数据
			othis.find('tbody>tr').each(function(i1) {
				var tr = $(this),
					row = {};
				//如果定义了字段名
				tr.children('td').each(function(i2, item2) {
					var td = $(this),
						field = td.data('field');
					if(field) {
						return row[field] = td.html();
					}
				});
				//如果未定义字段名
				layui.each(cols, function(i3, item3) {
					var td = tr.children('td').eq(i3);
					row[item3.field] = td.html();
				});
				options.data[i1] = row;
			});
			table.render(options);
		});

		return that;
	};

	//记录所有实例
	thisTable.that = {}; //记录所有实例对象
	thisTable.config = {}; //记录所有实例配置项

	//遍历表头
	table.eachCols = function(id, callback, cols) {
		var config = thisTable.config[id] || {},
			arrs = [],
			index = 0;

		cols = $.extend(true, [], cols || config.cols);

		//重新整理表头结构
		layui.each(cols, function(i1, item1) {
			layui.each(item1, function(i2, item2) {

				//如果是组合列，则捕获对应的子列
				if(item2.colGroup) {
					var childIndex = 0;
					index++
					item2.CHILD_COLS = [];

					layui.each(cols[i1 + 1], function(i22, item22) {
						//如果子列已经被标注为{PARENT_COL_INDEX}，或者子列累计 colspan 数等于父列定义的 colspan，则跳出当前子列循环
						if(item22.PARENT_COL_INDEX || (childIndex > 1 && childIndex == item2.colspan)) return;

						item22.PARENT_COL_INDEX = index;

						item2.CHILD_COLS.push(item22);
						childIndex = childIndex + parseInt(item22.colspan > 1 ? item22.colspan : 1);
					});
				}

				if(item2.PARENT_COL_INDEX) return; //如果是子列，则不进行追加，因为已经存储在父列中
				arrs.push(item2)
			});
		});

		//重新遍历列，如果有子列，则进入递归
		var eachArrs = function(obj) {
			layui.each(obj || arrs, function(i, item) {
				if(item.CHILD_COLS) return eachArrs(item.CHILD_COLS);
				typeof callback === 'function' && callback(i, item);
			});
		};

		eachArrs();
	};

	//表格选中状态
	table.checkStatus = function(id) {
		var nums = 0,
			invalidNum = 0,
			arr = [],
			data = table.cache[id] || [];
		//计算全选个数
		layui.each(data, function(i, item) {
			if(item.constructor === Array) {
				invalidNum++; //无效数据，或已删除的
				return;
			}
			if(item[table.config.checkName]) {
				nums++;
				arr.push(table.clearCacheKey(item));
			}
		});
		return {
			data: arr //选中的数据
			,isAll: data.length ? (nums === (data.length - invalidNum)) : false //是否全选
		};
	};

	//重置表格尺寸结构
	table.resize = function(id) {
		//如果指定表格唯一 id，则只执行该 id 对应的表格实例
		if(id) {
			var config = getThisTableConfig(id); //获取当前实例配置项
			if(!config) return;

			thisTable.that[id].resize();

		} else { //否则重置所有表格实例尺寸
			layui.each(thisTable.that, function() {
				this.resize();
			});
		}
	};

	//表格重载
	table.reload = function(id, options) {
		options = options || {};

		var config = getThisTableConfig(id); //获取当前实例配置项
		if(!config) return;

		if(options.data && options.data.constructor === Array) delete config.data;
		return table.render($.extend(true, {}, config, options));
	};

	//核心入口
	table.render = function(options) {
		var inst = new Class(options);
		return thisTable.call(inst);
	};

	//清除临时Key
	table.clearCacheKey = function(data) {
		data = $.extend({}, data);
		delete data[table.config.checkName];
		delete data[table.config.indexName];
		return data;
	};

	//自动完成渲染
	table.init();

	exports(MOD_NAME, table);
});